/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.server.controller.contentType;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import javax.servlet.http.HttpServletRequest;
import offset.nodes.Constants;
import offset.nodes.server.controller.AttributeConstants;
import offset.nodes.server.model.RepositoryModel;

/**
 *
 * @author Walter L�tgenau
 */
public class ChildNodeContentTypeMapper implements ContentTypeMapper {

    /**
     * Implement the content type mapper interface for non existing nodes, that have an
     * ancestor node, that already exists and the node type of the target node can be
     * determined by the path starting from the existing node.
     * 
     * If that nodeType has a property "contentType" which in turn
     * has a defaultValue, return the default Value.
     * 
     * @param node
     * @param request
     * @return
     * @throws RepositoryException
     */
    @Override
    public String getContentType(Node node, HttpServletRequest request) throws RepositoryException {
        if (node != null)
            return null;

        Session session = (Session) request.getSession().getAttribute(AttributeConstants.ATT_REPOSITORY_SESSION);
        RepositoryModel model = new RepositoryModel(session);

        String path = request.getPathInfo().replaceAll("\\+", " ");
        Node lastExisting = model.findLastExistingNode(path);
        if (lastExisting == null)
            return null;
        
        int pathIndex = path.indexOf(lastExisting.getPath());
        if (pathIndex < 0)
            return null;

        if (pathIndex + lastExisting.getPath().length() + 1 >= request.getPathInfo().length())
            return null;

        String remainingPath = request.getPathInfo().substring(pathIndex + lastExisting.getPath().length() + 1);
        String[] remainingComponents = remainingPath.split(Constants.PATH_SEPARATOR);

        NodeType type = lastExisting.getPrimaryNodeType();

        for (String component : remainingComponents) {
            boolean found = false;

            // discard index indication
            component = component.replaceAll("\\[.*\\]", "");

            for (NodeDefinition childDefinition : type.getChildNodeDefinitions()) {
                if (component.equals(childDefinition.getName())) {
                    type = childDefinition.getDefaultPrimaryType();
                    found = true;
                    break;
                }

            }

            if (!found)
                return null;
        }

        // search content type property in type
        String result = getContentType(type);
        if (result != null)
            return result;

        // search content type property in supertypes
        for (NodeType superType : type.getSupertypes()) {
            result = getContentType(superType);
            if (result != null)
                return result;
        }

        return null;
    }

    /**
     * Search the contentType property from the type. If it has
     * a default value, return the value.
     * 
     * @param type
     * @return
     * @throws RepositoryException
     */
    protected String getContentType(NodeType type) throws RepositoryException {
        for (PropertyDefinition propertyDefinition : type.getPropertyDefinitions()) {
            if (propertyDefinition.getName().equals(Constants.PROP_CONTENT_TYPE)
                    && propertyDefinition.getDefaultValues() != null
                    && propertyDefinition.getDefaultValues().length > 0)
                return propertyDefinition.getDefaultValues()[0].getString();
        }

        return null;
    }
}
